package com.weihong.demo.trade;

import com.futu.openapi.pb.TrdCommon;
import com.futu.openapi.pb.TrdGetOrderList;
import com.weihong.demo.evn.Config;
import com.weihong.demo.evn.MD5Util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;

@Service
public class PositionSell {
    private static final Logger logger = LoggerFactory.getLogger(PositionSell.class);

    @Value("${futu.password}")
    private String password;
    private String pwdMd5 = null;

    @Value("${futu.evn}")
    public int trdEnv;

    @Value("${futu.uid}")
    public long uid;
    public Long account = null;

    @Autowired
    private PositionService positionService;

    @Autowired
    private OrderListService orderListService;

    @Autowired
    private AccountListService accountListService;

    @Autowired
    private SellService sellService;

    private Set<Long> doneOrderNoSet = new HashSet<>();


    @Scheduled(cron = "*/9 * * * * ?")
    public void startUsPremiumJob() {
        doJob();
    }

    private synchronized void doJob() {
        if (account == null) {
            account = accountListService.getAccount(uid, trdEnv, TrdCommon.TrdMarket.TrdMarket_HK);
            logger.info("start to process:{},{}", trdEnv, account);
        }

        TrdGetOrderList.S2C orderList = orderListService.getOrderList(trdEnv, account);
        if (orderList == null || orderList.getOrderListList().isEmpty()) {
            logger.info("no order");
            return;
        }
        Map<String, Double> needToShell = fill(orderList);

        if (pwdMd5 == null) {
            pwdMd5 = MD5Util.calcMD5(password + "");
        }
        Map<String, TrdCommon.Position> positionMap = positionService.getpositionMap(trdEnv, account, pwdMd5);

        if (positionMap == null || positionMap.isEmpty() || needToShell.isEmpty()) {
            logger.info("no position");
            return;
        }

        positionMap.forEach((code, position) -> {
            if (needToShell.containsKey(code)) {
                double qty = Math.min(position.getCanSellQty(), needToShell.get(code));
                if(qty <0.0001){
                    return;
                }
                double price = position.getPrice() - 0.001;
                logger.info("start to sell code:{},qty:{},price:{}", code, qty,price);
                sellService.sell(trdEnv, account, code, (int) qty, price, TrdCommon.TrdSide.TrdSide_Sell);
            }
        });
    }

    private Map<String, Double> fill(TrdGetOrderList.S2C s2C) {
        Map<String, Double> result = new HashMap<>();
        List<TrdCommon.Order> orderList = s2C.getOrderListList();
        LocalDateTime endTime = LocalDateTime.now().minusMinutes(5);
        for (TrdCommon.Order order : orderList) {
            LocalDateTime orderTime;
            try{
                orderTime = LocalDateTime.parse(order.getUpdateTime(), Config.futuOrderTime);
            }catch (Exception e){
                orderTime = LocalDateTime.parse(order.getUpdateTime(), Config.futuTime);
            }
            long orderID = order.getOrderID();
            if (orderTime.isBefore(endTime) && !doneOrderNoSet.contains(orderID)) {
                result.put(order.getCode(), order.getQty());
                doneOrderNoSet.add(orderID);
            }
        }

        return result;
    }
}
